package lg.minecraft.plugin.pokemonmenu.util.pokemondata.storage;

import com.cobblemon.mod.common.pokemon.Pokemon;
import lg.minecraft.plugin.cobblemoncore.util.BukkitNmsConverter;
import net.minecraft.class_2487;
import net.minecraft.class_2507;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.*;
import java.util.Base64;
import java.util.UUID;

/**
 * @author langle__
 * @version 1.0
 */
public abstract class PokemonDataStorage {

    @Nullable
    public abstract Pokemon getPokemon(@NotNull UUID uuid);

    public abstract boolean savePokemon(@NotNull UUID uuid, @NotNull Pokemon pokemon);

    public abstract boolean removePokemon(@NotNull UUID uuid);

    public class_2487 toNBT(@NotNull Pokemon pokemon) {
        return pokemon.saveToNBT(BukkitNmsConverter.getRegistryAccess(), new class_2487());
    }

    public Pokemon fromNBT(class_2487 nbt) {
        return Pokemon.Companion.loadFromNBT(BukkitNmsConverter.getRegistryAccess(), nbt);
    }

    /**
     * 将Pokemon对象编码为Base64字符串
     * @param pokemon 要编码的Pokemon对象
     * @return Base64编码后的字符串
     */
    public String toBase64(@NotNull Pokemon pokemon) {
        class_2487 nbt = toNBT(pokemon);
        ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();
        try (DataOutputStream output = new DataOutputStream(byteOutput)) {
            class_2507.method_10628(nbt, output);
            return Base64.getEncoder().encodeToString(byteOutput.toByteArray());
        } catch (IOException e) {
            throw new RuntimeException("Failed to encode Pokemon to Base64", e);
        }
    }

    /**
     * 从Base64字符串解码为Pokemon对象
     * @param base64String Base64编码的字符串
     * @return 解码后的Pokemon对象
     * @throws IllegalArgumentException 如果Base64字符串无效或无法解析为Pokemon对象
     */
    public Pokemon fromBase64(@NotNull String base64String) throws IllegalArgumentException {
        try {
            byte[] bytes = Base64.getDecoder().decode(base64String);
            ByteArrayInputStream byteInput = new ByteArrayInputStream(bytes);
            DataInputStream input = new DataInputStream(byteInput);
            class_2487 nbt = class_2507.method_10627(input);
            return fromNBT(nbt);
        } catch (IOException e) {
            throw new IllegalArgumentException("Invalid Base64 string or failed to decode", e);
        }
    }

}
